package com.yanqu.road.server.manger.manor;

import com.yanqu.road.entity.config.fishpond.FishPondBadgeConfig;
import com.yanqu.road.entity.config.fishpond.FishPondEventInfo;
import com.yanqu.road.entity.config.fishpond.FishPondItemConfig;
import com.yanqu.road.entity.config.goods.GoodsBagInfo;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.config.skill.SkillInfo;
import com.yanqu.road.entity.config.skill.SkillUpgradeInfo;
import com.yanqu.road.entity.enums.eFishPondEventType;
import com.yanqu.road.entity.enums.eFishingEventType;
import com.yanqu.road.entity.enums.eGoodsType;
import com.yanqu.road.entity.enums.eSkillType;
import com.yanqu.road.entity.manor.*;
import com.yanqu.road.entity.player.PatronsFishBindingData;
import com.yanqu.road.entity.task.TaskConditionInfo;
import com.yanqu.road.logic.bussiness.config.FishPondConfigBusiness;
import com.yanqu.road.logic.bussiness.config.NpcConfigBussiness;
import com.yanqu.road.logic.bussiness.player.UserFishPondBusiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.pb.manor.FishPondProto;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.manor.ManorFishPondModel;
import com.yanqu.road.server.gameplayer.module.manor.ManorModule;
import com.yanqu.road.server.gameplayer.module.manor.fishPondTaskCondition.BaseFishPondCondition;
import com.yanqu.road.server.manger.config.GoodsBagMgr;
import com.yanqu.road.server.manger.config.GoodsMgr;
import com.yanqu.road.server.manger.config.SkillMgr;
import com.yanqu.road.server.manger.config.TaskMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.server.pb.FishPondPb;
import com.yanqu.road.utils.RandomHelper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author ：zfr
 * @date ：2021/10/14 10:37
 */
public class FishPondMgr extends TempMgr {
    private static Map<Integer, FishPondItemConfig> fishPondItemConfigMap;
    private static List<FishPondEventInfo> fishPondEventInfos;
    private static Map<Integer, FishPondBadgeConfig> fishPondBadgeConfigMap;
    public static int FISHING_JUDGING_OVER_TIME_SECOND = 20;     //判定超时时间
    private static Logger logger = LogManager.getLogger(FishPondMgr.class.getName());
    private static Random threadSafeRandom = new Random();
    private static RandomHelper randomHelper = new RandomHelper();
    private static Map<Integer, Map<Long, Integer>> fishingRarityFishReRandomMap; //钓珍稀鱼重随概率map 品质;累计钓起数量;概率



    @Override
    public boolean init() throws Exception {
        return reload();
    }

    public static FishPondItemConfig getFishPondItemConfig(int fishId) {
        return fishPondItemConfigMap.get(fishId);
    }

    public static FishPondEventInfo getFishPondEventInfo(int eventId) {
        for (FishPondEventInfo eventInfo : fishPondEventInfos) {
            if (eventInfo.getEventId() == eventId) {
                return eventInfo;
            }
        }
        return null;
    }


    /**
     * 检查鱼塘是否开启
     * @return bool
     */
    public static  boolean checkFishPondOpen(GamePlayer player) {
        UserManorData userManorData = player.getModule(ManorModule.class).getUserManorData();
        if (userManorData == null) {
            return false;
        }
        return player.getModule(ManorModule.class).getUserManorData().getProsperousValue() >= GameConfig.FISHPOND_OPEN_MANOR_PROSPEROUS_LIMIT;
    }

    /**
     * 随机钓鱼事件
     *
     *
     * @param taskConditionMap 委托任务
     * @param fishPondSpecialItemDataMap 奇物数据
     * @return eventInfo
     */
    public static FishPondEventInfo randomFishingEvent(Map<Long, BaseFishPondCondition> taskConditionMap, Map<Integer, FishPondSpecialItemData> fishPondSpecialItemDataMap, int weather, int dayNight, Map<Integer, FishData> fishDataMap) {
        List<FishPondEventInfo> eventList = fishPondEventInfos.stream()
                .filter(fishPondEventInfo -> canRandomEvent(taskConditionMap, fishPondSpecialItemDataMap, weather, dayNight, fishDataMap, fishPondEventInfo))
                .collect(Collectors.toList());
        List<Integer> weightList = eventList.stream().map(FishPondEventInfo::getWeight).collect(Collectors.toList());
        int index = RandomHelper.getRandomIndexByWeight(weightList, threadSafeRandom);
        return eventList.get(index);
    }

    /**
     * 是否可以随机事件
     *
     *
     * @param taskConditionMap  委托任务
     * @param fishPondSpecialItemDataMap 奇物数据
     * @param weather   天气
     * @param dayNight  昼夜
     * @param eventInfo 事件配置
     * @return bool
     */
    private static boolean canRandomEvent(Map<Long, BaseFishPondCondition> taskConditionMap, Map<Integer, FishPondSpecialItemData> fishPondSpecialItemDataMap, int weather, int dayNight, Map<Integer, FishData> fishDataMap, FishPondEventInfo eventInfo) {
        if (eventInfo.getType() == eFishingEventType.Task.getValue()) {
            //鱼的数量少于2条,去钓鱼
            if (fishDataMap.size() < 2) {
                return false;
            }
            //任务满了 不能再搞任务了
            if (checkTaskFull(taskConditionMap)) {
                return false;
            }
            return TaskMgr.getTaskConditionById(Integer.parseInt(eventInfo.getExtendParam().split("\\|")[0])) != null;
        }
        if (eventInfo.getType() == eFishingEventType.Fish.getValue()) {
            List<GoodsBagInfo> goodsBagInfoList = GoodsBagMgr.getGoodsBagInfoList(Integer.parseInt(eventInfo.getReward()));
            for (GoodsBagInfo goodsBagInfo : goodsBagInfoList) {
                if (canRandomFish(goodsBagInfo, weather, dayNight, fishDataMap, true)) {
                    return true;
                }
            }
            return false;
        }
        if (eventInfo.getType() == eFishingEventType.SpecialItem.getValue()) {
            if (fishDataMap.size() < 2) {
                return false;
            }
            Map<Integer, Long> specialItemTaskValueMap = getSpecialItemTaskValueMap(taskConditionMap);
            for (Map.Entry<Integer, Long> entry : specialItemTaskValueMap.entrySet()) {
                GoodsInfo goodsInfo = GoodsMgr.getGoodsById(Integer.parseInt(eventInfo.getReward().split("=")[0]));
                if (canRandomSpecialItem(goodsInfo, entry.getKey())) {
                    if (fishPondSpecialItemDataMap.get(entry.getKey()) == null) {
                        return true;
                    }
                    if (fishPondSpecialItemDataMap.get(entry.getKey()).getCount() < entry.getValue()) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    private static Map<Integer, Long> getSpecialItemTaskValueMap(Map<Long, BaseFishPondCondition> taskConditionMap) {
        Map<Integer, Long> taskValueMap = new HashMap<>();
        //有接到相对应的奇物任务 才能钓到奇物
        for (BaseFishPondCondition condition : taskConditionMap.values()) {
            if (!condition.isGetReward()) {
                TaskConditionInfo taskConditionInfo = TaskMgr.getTaskConditionById(condition.getFishPondTaskData().getTaskId());
                if (taskConditionInfo.getType() == eFishPondEventType.FishingTypeSpecialItemCount.getIntValue()) {
                    int itemId = taskConditionInfo.getParamList().get(2).intValue();
                    if (!taskValueMap.containsKey(itemId)) {
                        taskValueMap.put(itemId, 0L);
                    }
                    taskValueMap.put(itemId, taskValueMap.get(itemId) + taskConditionInfo.getParamList().get(3).longValue());
                }
            }
        }
        return taskValueMap;
    }

    /**
     * 检查委托任务是否已满
     * @return bool
     */
    private static boolean checkTaskFull(Map<Long, BaseFishPondCondition> taskConditionMap) {
        long count = taskConditionMap.values().stream().filter(condition -> !condition.isGetReward()).count();
        return count >= GameConfig.FISHPOND_TASK_NUM_LIMIT;
    }

    /**
     * 配置是否允许随机鱼类事件
     * @param goodsBagInfo 鱼类事件箱子配置
     * @param weather 天气
     * @param dayNight 昼夜
     * @param fishDataMap 鱼类数据
     * @param isReRandom
     * @return bool
     */
    private static boolean canRandomFish(GoodsBagInfo goodsBagInfo, int weather, int dayNight, Map<Integer, FishData> fishDataMap, boolean isReRandom) {
        FishPondItemConfig fishPondItemConfig = fishPondItemConfigMap.get(goodsBagInfo.getGoodsId());
        if (Integer.parseInt(GameConfig.FISHPOND_INITIAL_PARAM.split("\\|")[2]) > fishDataMap.size()) {
            if (fishDataMap.containsKey(fishPondItemConfig.getId())) {
                return false;
            }
        }
        if (fishPondItemConfig != null) {
            return (fishPondItemConfig.getWeather() == weather || fishPondItemConfig.getWeather() == 0) &&
                    (fishPondItemConfig.getTime() == dayNight || fishPondItemConfig.getTime() == 0) &&
                    (!isReRandom || fishPondItemConfig.getQuality() < GameConfig.FISHPOND_FISH_RARITY_QUALITY_LIMIT) &&
                    checkFishCondition(fishPondItemConfig, fishDataMap);
        }
        return false;
    }

    //前置条件
    private static boolean checkFishCondition(FishPondItemConfig fishPondItemConfig, Map<Integer, FishData> fishDataMap) {
        String fishCondition = fishPondItemConfig.getFishCondition();
        if (fishCondition.equals("0") || fishCondition.isEmpty()) {
            return true;
        }
        String[] split = fishCondition.split(";");
        int fishId = Integer.parseInt(split[0]);
        int needLv = Integer.parseInt(split[1]);
        FishData fishData = fishDataMap.get(fishId);
        return fishData != null && fishData.getLv() >= needLv;
    }

    /**
     * 获取当前条件下能钓起的未满阶的无双鱼
     * @param goodsBagInfoList
     * @param weather
     * @param dayNight
     * @param fishDataMap
     * @return
     */
    public static List<FishPondItemConfig> getCanRandomWushuangFishList(List<GoodsBagInfo> goodsBagInfoList, int weather, int dayNight, Map<Integer, FishData> fishDataMap) {
        List<FishPondItemConfig> canRandomFishList = new ArrayList<>();
        for (GoodsBagInfo goodsBagInfo : goodsBagInfoList) {
            FishPondItemConfig config = fishPondItemConfigMap.get(goodsBagInfo.getGoodsId());
            if (config != null && config.getQuality() == 5 && (config.getWeather() == weather || config.getWeather() == 0) &&
                    (config.getTime() == dayNight || config.getTime() == 0)) {
                FishData fishData = fishDataMap.get(config.getId());
                if (fishData == null) {
                    canRandomFishList.add(config);
                    continue;
                }
                //判断是否已经满阶或数量足够晋升至满阶
                int upgradeSkillId = FishPondMgr.getFishUpgradeSkillConfig(config.getId());
                if (upgradeSkillId != 0) {
                    SkillInfo skillInfo = SkillMgr.getSkillInfo(upgradeSkillId);
                    if (skillInfo != null) {
                        if (skillInfo.getMaxLevel() <= fishData.getLv()) {
                            //满阶了
                            continue;
                        }
                        // 前置条件是否满足
                        if (!checkFishCondition(config, fishDataMap)) {
                            continue;
                        }
                        long totalConsume = SkillMgr.getTotalConsumeOfSkillUpgradeMaxLevel(skillInfo.getUpgradeType(0), fishData.getLv());
                        if (fishData.getNum() >= totalConsume) {
                            // 数量足够晋升至满阶
                            continue;
                        }
                    }
                }
                canRandomFishList.add(config);
            }
        }
        return canRandomFishList;
    }

    private static boolean canRandomSpecialItem(GoodsInfo goodsInfo, int itemId) {
        return goodsInfo != null && goodsInfo.getType() == eGoodsType.FishPondSpecialItem.getValue() && goodsInfo.getGoodsId() == itemId;
    }

    /**
     * 随机鱼类
     * @param boxId rewardBoxId
     * @param weather 天气
     * @param dayNight 昼夜
     * @param fishDataMap 鱼类数据
     * @return config
     */
    public static FishPondItemConfig randomFish(int boxId, int weather, int dayNight, Map<Integer, FishData> fishDataMap, boolean isReRandom,int baitId) {
        try {
            if (fishDataMap.size() < 2) {
                String[] split = GameConfig.FISHPOND_INITIAL_PARAM.split("\\|");
                if (fishDataMap.size() == 0) {
                    return fishPondItemConfigMap.get(Integer.parseInt(split[0]));
                } else {
                    return fishPondItemConfigMap.get(Integer.parseInt(split[1]));
                }
            }
        } catch (Exception e) {
            logger.error("fishing guide error", e);
        }
        List<GoodsBagInfo> goodsBagInfoList = GoodsBagMgr.getGoodsBagInfoList(boxId);
        List<GoodsBagInfo> randomList = goodsBagInfoList.stream()
                .filter(goodsBagInfo -> canRandomFish(goodsBagInfo, weather, dayNight, fishDataMap, isReRandom))
                .collect(Collectors.toList());
        List<Integer> weightList = randomList.stream().map(GoodsBagInfo::getRandomWeight).collect(Collectors.toList());
        int index = RandomHelper.getRandomIndexByWeight(weightList, threadSafeRandom);
        FishPondItemConfig fishPondItemConfig = fishPondItemConfigMap.get(randomList.get(index).getGoodsId());
        if (fishPondItemConfig == null) {
            getLogger().error("random fish result is null, goodsId:{}", randomList.get(index).getGoodsId());
        } else {
            //随到了珍稀鱼
            if (fishPondItemConfig.getQuality() >= GameConfig.FISHPOND_FISH_RARITY_QUALITY_LIMIT && !isReRandom) {
                //玩家没钓起过这条鱼 判定一下是否需要重随
                if (!fishDataMap.containsKey(fishPondItemConfig.getId())) {
                    //取玩家鱼类数据里面该品质的鱼的种类数量
                    int haveCount = 0;
                    for (FishData fishData : fishDataMap.values()) {
                        FishPondItemConfig config = getFishPondItemConfig(fishData.getFishId());
                        if (config.getQuality() == fishPondItemConfig.getQuality()) {
                            haveCount++;
                        }
                    }
                    //根据真实钓起的数量取重随概率
                    Integer reRandomWeight = getReRandomWeight(fishPondItemConfig.getQuality(), haveCount);
                    if (reRandomWeight != null) {
                        int randomValue = randomHelper.next(1000);
                        //概率命中 就重新随机非珍稀鱼
                        if (randomValue < reRandomWeight) {
                            return randomFish(boxId, weather, dayNight, fishDataMap, true,baitId);
                        }
                    }
                }
            }
        }
        if (fishPondItemConfig != null && fishPondItemConfig.getQuality() == 5) {
            //如果用的是赤龙鱼饵，且随机到无双鱼，就用新的宝箱代替之前的无双宝箱随机鱼
            if(baitId == GameConfig.FISHPOND_FISHING_RED_WORM_ITEM_ID){
                goodsBagInfoList = GoodsBagMgr.getGoodsBagInfoList(GameConfig.FISHPOND_FISHING_RED_WORM_BOX_ID);
            }
            List<FishPondItemConfig> fishList = getCanRandomWushuangFishList(goodsBagInfoList, weather, dayNight, fishDataMap);
            if (fishList.size() == 0 || fishList.contains(fishPondItemConfig)) {
                return fishPondItemConfig;
            }
            return fishList.get(randomHelper.next(fishList.size()));
        }
        return fishPondItemConfig;
    }

    /**
     * 获取重随概率
     * @param quality 品质
     * @param realFishingCount 累计真实钓起数量
     * @return randomWeight
     */
    private static Integer getReRandomWeight(int quality, long realFishingCount) {
        Integer maxCountReRandomWeight = null;
        Map<Long, Integer> randomMap = fishingRarityFishReRandomMap.get(quality);
        if (randomMap == null) {
            return maxCountReRandomWeight;
        }
        if (randomMap.containsKey(realFishingCount)) {
            return randomMap.get(realFishingCount);
        }

        long compareCount = 0L;
        for (Map.Entry<Long, Integer> entry : randomMap.entrySet()) {
            if ((compareCount == 0 && realFishingCount >= entry.getKey()) || (entry.getKey() > compareCount && realFishingCount >= entry.getKey())) {
                maxCountReRandomWeight = entry.getValue();
                compareCount = entry.getKey();
            }
        }
        return maxCountReRandomWeight;
    }

    /**
     * 随机鱼的重量
     * @param config 鱼类配置
     * @return weight
     */
    public static int randomFishWeight(FishPondItemConfig config) {
        String[] weightSplit = config.getWeight().split(",");
        return randomHelper.next(Integer.parseInt(weightSplit[0]), Integer.parseInt(weightSplit[1]));
    }

    /**
     * 获取昼夜
     * @return 1;0
     */
    public static int getDayNight() {
        String[] dayTime = GameConfig.MANOR_DAY_NIGHT_TIME.split(",");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        int nowHour = calendar.get(Calendar.HOUR_OF_DAY);
        return (nowHour >= Integer.parseInt(dayTime[0]) && nowHour < Integer.parseInt(dayTime[1])) ? 1 : 2;
    }

    /**
     * 初始鱼塘体力领取时间
     * @return TimeMillis
     */
    public static long initRecoveryTime() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        cal.add(Calendar.MINUTE, -1 * Integer.parseInt(GameConfig.FISHPOND_ENERGY_RECOVERY_PARAM.split(",")[2]) * Integer.parseInt(GameConfig.FISHPOND_ENERGY_RECOVERY_PARAM.split(",")[1]));
        return cal.getTimeInMillis();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        Map<Integer, FishPondBadgeConfig> tempMap = FishPondConfigBusiness.getFishPondBadgeConfigMap();
        checkBadgeConfigValidity(tempMap);
        Map<Integer, FishPondItemConfig> fishPondItemConfigTempMap = FishPondConfigBusiness.getFishPondItemConfigMap();
        checkSkillValidity(fishPondItemConfigTempMap);
        fishPondItemConfigMap = fishPondItemConfigTempMap;
        fishPondBadgeConfigMap = tempMap;
        fishPondEventInfos = NpcConfigBussiness.getFishPondEventInfoList();
        parseFishingRarityFishReRandomMap();
        return true;
    }

    private void checkBadgeConfigValidity(Map<Integer, FishPondBadgeConfig> tempMap) {
        if (tempMap.size() == 0) {
            throw new RuntimeException("fishPondBadgeConfig is null");
        }

        for (FishPondBadgeConfig pondBadgeConfig : tempMap.values()) {
            if (pondBadgeConfig.getId() == 0) {
                throw new RuntimeException("fishPondBadgeConfig id is 0");
            }
        }
    }

    private void parseFishingRarityFishReRandomMap() {
        Map<Integer, Map<Long, Integer>> tempMap = new ConcurrentHashMap<>();
        String[] paramSplit = GameConfig.FISHPOND_RARITY_FISHING_DIMINISHING_PARAM.split("\\|");
        for (int i = 0; i < paramSplit.length; i++) {
            String paramStr = paramSplit[i];
            if (paramStr.isEmpty() || paramStr.equals("0")) {
                continue;
            }
            Map<Long, Integer> randomMap = new ConcurrentHashMap<>();
            String[] randomSplit = paramStr.split(";");
            for (String randomStr : randomSplit) {
                String[] split = randomStr.split("-");
                randomMap.put(Long.valueOf(split[0]), Integer.parseInt(split[1]));
            }
            tempMap.put(i + GameConfig.FISHPOND_FISH_RARITY_QUALITY_LIMIT, randomMap);
        }
        fishingRarityFishReRandomMap = tempMap;
    }

    public static Map<Integer, FishPondBadgeConfig> getFishPondBadgeConfigMap() {
        return fishPondBadgeConfigMap;
    }

    /**
     * 检测鱼类技能配置合法性 ,首个技能配置 等级要求为0 是晋升相关配置
     * @param fishPondItemConfigTempMap
     */
    private void checkSkillValidity(Map<Integer, FishPondItemConfig> fishPondItemConfigTempMap) {
        for (FishPondItemConfig fishPondItemConfig : fishPondItemConfigTempMap.values()) {
            if (fishPondItemConfig.getSkills().isEmpty() || fishPondItemConfig.getSkills().equals("0")) {
                continue;
            }
            String[] skillConfigArr = fishPondItemConfig.getSkills().split("\\|");
            String[] skillConfig = skillConfigArr[0].split(",");
            if (Integer.parseInt(skillConfig[1]) != 0) {
                getLogger().error("fish skill config error, fish config id:{}", fishPondItemConfig.getId());
                throw new RuntimeException("fish skill config error");
            }
        }
    }

    /**
     * 获取鱼塘徽章下一级配置
     * @param id 当前等级id
     * @return config
     */
    public static FishPondBadgeConfig getNextFishPondBadgeConfig(int id) {
        List<Integer> idList = new ArrayList<>(fishPondBadgeConfigMap.keySet());
        Collections.sort(idList);
        if (id == 0) {
            id = idList.get(0);
        }
        int index = idList.indexOf(id);
        if (index != -1) {
            return fishPondBadgeConfigMap.get(idList.get(index + 1));
        }
        return null;
    }

    public static int getInitBadgeLv() {
        List<Integer> idList = new ArrayList<>(fishPondBadgeConfigMap.keySet());
        Collections.sort(idList);
        return idList.get(0);
    }

    /**
     * 随机任务的npc形象
     * @param npcIdStr npc
     * @return npcId
     */
    public static int randomTaskNpcId(String npcIdStr) {
        List<Integer> npcIdList = Arrays.stream(npcIdStr.split(",")).map(Integer::parseInt).collect(Collectors.toList());
        int index = randomHelper.next(npcIdList.size());
        return npcIdList.get(index);
    }

    public static int randomTaskTextIndex(int maxIndex) {
        return randomHelper.next(maxIndex);
    }

    /**
     * 是否是珍稀鱼
     * @param config 鱼类配置
     * @return bool
     */
    public static boolean isRarityFish(FishPondItemConfig config) {
        return config.getQuality() >= GameConfig.FISHPOND_FISH_RARITY_QUALITY_LIMIT;
    }

    /**
     * 获取鱼类晋升的技能配置id
     * @param fishId 鱼类id
     * @return skillId
     */
    public static int getFishUpgradeSkillConfig(int fishId) {
        FishPondItemConfig fishPondItemConfig = fishPondItemConfigMap.get(fishId);
        String skills = fishPondItemConfig.getSkills();
        String[] skillsArr = skills.split("\\|");
        if (skillsArr.length <= 0) {
            return 0;
        }
        String[] split = skillsArr[0].split(",");
        return Integer.parseInt(split[1]) == 0 ? Integer.parseInt(split[0]) : 0;
    }

    public static int getFishEquipCost(int buyTimes) {
        int ingots = GameConfig.FISHPOND_EQUIP_BASE_COST + GameConfig.FISHPOND_EQUIP_ADD_COST * buyTimes;
        if(ingots < 0){
            ingots = 0;
        }
        if(ingots > GameConfig.FISHPOND_EQUIP_MAX_COST){
            ingots = GameConfig.FISHPOND_EQUIP_MAX_COST;
        }
        return ingots;
    }

    /**
     * 获取拜访数据
     * @param userId 玩家id
     * @return msg
     */
    public static FishPondProto.VisitOtherFishPondRespMsg.Builder getVisitMsg(long userId) {
        FishPondProto.VisitOtherFishPondRespMsg.Builder respMsg;
        GamePlayer onlinePlayer = GamePlayerMgr.getOnlinePlayer(userId);
        Map<Integer, FishData> fishDataMap = new ConcurrentHashMap<>();
        FishPondData fishPondData = null;
        if (onlinePlayer != null) {
            ManorFishPondModel model = onlinePlayer.getModule(ManorModule.class).getManorFishPondModel();
            if (model != null) {
                fishDataMap = model.getFishDataMap();
                fishPondData = model.getFishPondData();
            }
        } else {
            fishDataMap = UserFishPondBusiness.getFishDataMap(userId);
            fishPondData = UserFishPondBusiness.getFishPondData(userId);
        }
        respMsg = FishPondPb.parseVisitOtherRespMsg(fishPondData, fishDataMap);
        return respMsg;
    }

    /**
     * 获取鱼塘徽章技能加成
     * @param player player
     * @return addLv
     */
    private static int getFishPondBadgeSkillAdd(GamePlayer player, int skillType, int buildingType) {
        int add = 0;
        ManorFishPondModel model = player.getModule(ManorModule.class).getManorFishPondModel();
        if (model != null) {
            if (model.getFishPondData() != null) {
                int fishPondLv = model.getFishPondData().getFishPondLv();
                for (FishPondBadgeConfig badgeConfig : fishPondBadgeConfigMap.values()) {
                    if (badgeConfig.getId() == fishPondLv) {
                        String[] skillSplit = badgeConfig.getSkillsList().split("\\|");
                        for (String skillIdStr : skillSplit) {
                            SkillInfo skillInfo = SkillMgr.getSkillInfo(Integer.parseInt(skillIdStr));
                            if (skillInfo.getType() == skillType) {
                                if (skillType == eSkillType.FishPondStageSkillMaxLevelAdd.getValue()) {
                                    add += SkillMgr.getSkillAddition(skillInfo, getBadgeLvById(fishPondLv));
                                } else if (skillType == eSkillType.ManorBuildingTypeEarnAddRatio.getValue()) {
                                    if (skillInfo.getParamList().get(2) == 0 || skillInfo.getParamList().get(2) == buildingType) {
                                        add += SkillMgr.getSkillAddition(skillInfo, getBadgeLvById(fishPondLv));
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return add;
    }

    public static int getStageSkillMaxLevelAdd(GamePlayer player, int skillType) {
        return getFishPondBadgeSkillAdd(player, skillType, 0);
    }

    public static int getBuildingSpeedAddition(GamePlayer player, int skillType, int buildingType) {
        return getFishPondBadgeSkillAdd(player, skillType, buildingType);
    }

    private static int getBadgeLvById(int badgeId) {
        List<Integer> idList = new ArrayList<>(fishPondBadgeConfigMap.keySet());
        Collections.sort(idList);
        int lv = 1;
        for (Integer id : idList) {
            if (badgeId == id) {
                return lv;
            }
            lv++;
        }
        return lv;
    }

    public static int getFishingConsumeNum(int times) {
        String[] split = GameConfig.FISHPOND_FISHING_COST_NUM.split(",");
        if (times == 1) {
            // 1连
            return Integer.parseInt(split[0]);
        } else if (times == 10) {
            // 10连
            return Integer.parseInt(split[1]);
        } else if (times == 100) {
            // 100连
            return Integer.parseInt(split[2]);
        }
        return times;
    }

    public static long calcCostExp(FishSkillData skillData) {
        long recycleExp = 0L;
        List<SkillUpgradeInfo> skillUpgradeInfoList = SkillMgr.getSkillUpgradeInfoList(SkillMgr.getSkillInfo(skillData.getFishSkillId()).getUpgradeType(0));
        for (SkillUpgradeInfo upgradeInfo : skillUpgradeInfoList) {
            if (upgradeInfo.getLevel() < skillData.getLv()) {
                recycleExp += upgradeInfo.getConsumeCount();
            }
        }
        return recycleExp + skillData.getCurExp();
    }

    public static FishData getUserFishByPatrons(int patronsId, Map<Integer, FishData> fishDataMap) {
        for (FishData fishData : fishDataMap.values()) {
            if (fishData.getEquipPatronsId() == patronsId) {
                return fishData;
            }
        }
        return null;
    }

    public static long getFishAddQualification(int patronsId, Map<Integer, FishData> fishDataMap) {
        int qualification = 0;
        FishData equipFishData = getUserFishByPatrons(patronsId, fishDataMap);
        if (equipFishData != null) {
            for (FishSkillData skillData : equipFishData.getFishSkillDataMap().values()) {
                SkillInfo skillInfo = SkillMgr.getSkillInfo(skillData.getFishSkillId());
                if (skillInfo != null && skillInfo.getType() == eSkillType.Qualification.getValue()) {
                    qualification += SkillMgr.getSkillAddition(skillInfo, skillData.getLv());
                }
            }
        }
        return qualification;
    }

    public static long getFishAddPercentage(int patronsId, Map<Integer, FishData> fishDataMap) {
        long addition = 0L;
        FishData equipFishData = getUserFishByPatrons(patronsId, fishDataMap);
        if (equipFishData != null) {
            int skillId = getFishUpgradeSkillConfig(equipFishData.getFishId());
            SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
            if (skillInfo != null && skillInfo.getType() == eSkillType.BeautyPatronsSkill2.getValue()) {
                addition += SkillMgr.getSkillAddition(skillInfo, equipFishData.getLv() + 1);
            }
        }
        return addition;
    }

    public static long getFishAbilityAddValue(int patronsId, Map<Integer, FishData> fishDataMap) {
        long addAbility = 0L;
        FishData equipFishData = getUserFishByPatrons(patronsId, fishDataMap);
        if (equipFishData != null) {
            int skillId = getFishUpgradeSkillConfig(equipFishData.getFishId());
            SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
            if (skillInfo != null && skillInfo.getType() == eSkillType.BeautyPatronsEscortSkill1.getValue()) {
                addAbility += SkillMgr.getSkillAddition(skillInfo, equipFishData.getLv() + 1);
            }
        }
        return addAbility;
    }

    public static void bindFishToPatrons(int activityId, long userId, int patronsId) {
        GamePlayer player = GamePlayerMgr.getOnlinePlayer(userId);
        if (player != null) {
            ManorFishPondModel fishPondModel = player.getModule(ManorModule.class).getManorFishPondModel();
            if (fishPondModel != null) {
                FishData fishData = getUserFishByPatrons(patronsId, fishPondModel.getFishDataMap());
                if (fishData != null) {
                    fishPondModel.addPatronsBindData(activityId, patronsId, fishData.getFishId());
                }
            }
        } else {
            Map<Integer, FishData> fishDataMap = UserFishPondBusiness.getFishDataMap(userId);
            int fishId = 0;
            for (FishData fishData : fishDataMap.values()) {
                if (fishData.getEquipPatronsId() == patronsId) {
                    fishId = fishData.getFishId();
                }
            }
            if (fishId != 0) {
                Map<Integer, PatronsFishBindingData> dataMap = UserFishPondBusiness.getPatronsFishBindingData(userId);
                PatronsFishBindingData data = dataMap.get(fishId);
                if (data == null) {
                    data = new PatronsFishBindingData();
                    data.setFishId(fishId);
                    data.setUserId(userId);
                    data.setInsertOption();
                }
                if (data.getActivityIdList().contains(activityId) && data.getPatronsId() == patronsId) {
                    return;
                }
                data.setPatronsId(patronsId);
                data.addActivityId(activityId);
                data.setLastUpdateTime(System.currentTimeMillis());

                if (data.isInsertOption()) {
                    UserFishPondBusiness.addPatronsFishBinding(data);
                } else {
                    UserFishPondBusiness.updatePatronsFishBinding(data);
                }
            }
        }
    }

    public static Map<Integer, FishData> getUserFishMap(long userId) {
        GamePlayer player = GamePlayerMgr.getOnlinePlayer(userId);
        if(null != player){
            ManorFishPondModel fishPondModel = player.getModule(ManorModule.class).getManorFishPondModel();
            if (fishPondModel != null) {
               return fishPondModel.getFishDataMap();
            }
        }else {
            return UserFishPondBusiness.getFishDataMap(userId);
        }
        return new ConcurrentHashMap<>();
    }

    public static Map<Long,Map<Integer, FishData>> getSomeUserFishMap(List<Long> userIdList) {
        return UserFishPondBusiness.getSomeFishDataMap(userIdList);
    }

    public static boolean isFishItem(int goodsId) {
        return fishPondItemConfigMap.containsKey(goodsId);
    }

    public static boolean isSpecialItem(int goodsId) {
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(goodsId);
        if (goodsInfo == null) {
            return false;
        }
        return goodsInfo.getType() == eGoodsType.FishPondSpecialItem.getValue();
    }

    public static Map<Integer, FishPondItemConfig> getFishPondItemConfigMap() {
        return fishPondItemConfigMap;
    }

    @Override
    public boolean reloadData() throws Exception {
        return true;
    }

    @Override
    public boolean stop() {
        return true;
    }
}
